package com.lzy.chat.c_service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lzy.chat.a_entity.GroupShip;
import com.lzy.chat.a_entity.Message;
import com.lzy.chat.a_entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class WebsocketService implements WebSocketHandler {
    //concurrent包的线程安全map，用来存放每个客户端对应的MyWebSocket对象。
    private static final ConcurrentHashMap<Integer, WebSocketSession> webSocket = new ConcurrentHashMap<>();

    private static final ObjectMapper objectMapper = new ObjectMapper();

    private static MessageService messageService;

    private static UserService userService;

    private static FriendService friendService;

    private static GroupService groupService;

    @Autowired
    public void setFriendService(FriendService friend) {
        friendService = friend;
    }

    @Autowired
    public void setMessageService(MessageService message) {
        messageService = message;
    }

    @Autowired
    public void setGroupService(GroupService group) {
        groupService = group;
    }

    @Autowired
    public void setUserService(UserService user) {
        WebsocketService.userService = user;
    }

    //连接成功后
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws IOException {
        int id = Integer.parseInt(session.getAttributes().get("id").toString());
        WebSocketSession s = webSocket.get(id);
        if (s != null) {
            Message message = new Message();
            message.setToId(id);
            message.setMessageType(7);
            s.sendMessage(encode(message));
            s.close();
        }
        webSocket.put(id, session);//加入map中
        onlineCount();
        //登录之后获取所有未读消息
        sendUnreadMessage(id, session);
        //未读群聊信息
        sendUnreadGroupMessage(id, session);
        sendFriendRequestNum(id, session);
        sendGroupRequestNum(id, session);

    }

    public void sendUnreadMessage(Integer uid, WebSocketSession session) throws IOException {
        List<Message> messages = messageService.getUnreadMessage(uid);
        for (Message m : messages) {
            session.sendMessage(encode(m));//发送消息
//            System.out.println(m.getId());
//            messageService.readMessage(m.getId());//设为已读
        }
    }

    public void sendUnreadGroupMessage(Integer uid, WebSocketSession session) throws IOException {
        List<GroupShip> groupShips = groupService.getGroupShipByUid(uid);
        for (GroupShip groupShip : groupShips) {
            List<Message> m = messageService.getUnreadGroupMessage(groupShip.getGid(), groupShip.getLastReadDate());
//            System.out.println(groupShip);
//            System.out.println(Arrays.toString(m.toArray()));
            groupService.updateLastReadDate(uid, groupShip.getGid(), new Date());//更新最后阅读时间
            for (Message message : m) {
                User u = userService.getInfoById(message.getFromId());
                message.setUser(u);
                session.sendMessage(encode(message));
            }
        }
    }

    public void sendGroupRequestNum(Integer uid, WebSocketSession session) throws IOException {
        List<Integer> group = groupService.getOnesManageGroup(uid);
        int count = 0;
        for (Integer gid : group) {
            count += groupService.countUnDeal(gid);
        }
        Message addFriend = new Message();
        addFriend.setMessageType(6);
        addFriend.setData(count + "");
        addFriend.setToId(uid);
        session.sendMessage(encode(addFriend));
    }

    public void sendFriendRequestNum(Integer uid, WebSocketSession session) throws IOException {
        //发送未处理好友申请个数
        Integer count = friendService.countUnDeal(uid);
        Message addFriend = new Message();
        addFriend.setMessageType(5);
        addFriend.setData(count + "");
        addFriend.setToId(uid);
        session.sendMessage(encode(addFriend));
    }


    //接收来自客户端的消息
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        if (message instanceof TextMessage) {
            Message m;
            try {
                m = decode(message);//解析为Message对象
                m.setSendDate(new Date());
                switch (m.getMessageType()) {
                    case 1, 2 -> {
                        m.setIsRead(0);
                        m = messageService.storeMessage(m);//储存消息
                        System.out.println(m);
                        session.sendMessage(encode(m));//向发送用户发送完整message对象
                        sendToUser(m);//向接收用户发送
                    }
                    case 3, 4 -> {
                        m = messageService.storeMessage(m);
                        System.out.println(m);
                        User user = userService.getInfoById(m.getFromId());
                        m.setUser(user);
                        sendToGroup(m);
                    }
                    case -1 -> sendToUser(m);//心跳消息
                    case -2 -> confirmFriendMessage(m);
                }
            } catch (JsonProcessingException e) {
                System.out.println("信息解析错误");
                session.sendMessage(new TextMessage("{\"message\":\"error\"}"));
            } catch (IOException e) {
                session.sendMessage(new TextMessage("{\"message\":\"error\"}"));
            }
        }
    }

    public static void confirmFriendMessage(Message m) {
        messageService.readMessage(Integer.parseInt(m.getData()));//设为已读
    }

    public static void sendToUser(Message m) throws IOException {
        Integer toId = m.getToId();
        WebSocketSession webSocketSession = webSocket.get(toId);
        //用户在线
        if (webSocketSession != null) {
            webSocketSession.sendMessage(encode(m));
        }
    }

    public static void sendToGroup(Message m) throws IOException {
        Integer gid = m.getToId();
        List<GroupShip> list = groupService.getGroupShipByGid(gid);
        for (GroupShip groupShip : list) {
            WebSocketSession session = webSocket.get(groupShip.getUid());
            if (session != null) {
                session.sendMessage(encode(m));
                //发送成功,更新最后阅读时间
                groupService.updateLastReadDate(groupShip.getUid(), gid, new Date());
            }
        }
    }

    //将textMessage中的getPayload()返回值转换成Message对象
    public static Message decode(WebSocketMessage<?> message) throws JsonProcessingException {
        return objectMapper.readValue(message.getPayload().toString(), Message.class);
    }

    //将Message对象转换成String
    public static WebSocketMessage<?> encode(Message message) throws JsonProcessingException {
        return new TextMessage(objectMapper.writeValueAsString(message));
    }

    //发生错误
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        exception.printStackTrace();
//        String id = session.getAttributes().get("id").toString();
//        WebSocketSession s = webSocket.remove(Integer.parseInt(id));
//        try {
//            s.close();
//        } catch (Exception ignored) {
//        }
//        onlineCount();
    }

    //关闭连接之后
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        String id = session.getAttributes().get("id").toString();
        WebSocketSession s = webSocket.remove(Integer.parseInt(id));
        try {
            if (s != null)
                s.close();
        } catch (IOException ignored) {
        }
        onlineCount();
    }

    @Override
    public boolean supportsPartialMessages() {
        return true;
    }


    public static void onlineCount() {
        System.out.println("当前用户在线:" + webSocket.size());
    }
}
